import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:hygf/http/file_transfer/down_cap.dart';
import 'package:hygf/http/file_transfer/upload_cap.dart';
import 'package:hygf/util/string_extension.dart';

import '../http/DioClient.dart';
import '../http/file_transfer/upload_request_option.dart';
import '../http/file_transfer/upload_result.dart';
import '../res/HDColors.dart';
import '../util/HDNavigator.dart';
import '../util/LoadingUtils.dart';
import 'image_picker_widget.dart';
import 'image_preview_page.dart';
import 'image_widget.dart';

/// 文件选择器
class FilePickerWidget extends StatefulWidget {
  FilePickerController controller;
  Function(List<ImagePickerData>)? onAdd;
  Function(ImagePickerData)? onRemove;
  bool? hidehead;
  bool? readonly;

  FilePickerWidget(
      {Key? key,
      required this.controller,
      this.onAdd,
      this.onRemove,
      this.hidehead,
      this.readonly})
      : super(key: key);

  @override
  _FilePickerWidgetState createState() => _FilePickerWidgetState();
}

class _FilePickerWidgetState extends State<FilePickerWidget> {
  @override
  void initState() {
    widget.controller._state = this;
    widget.controller.mcallback = choiceFiles;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.topCenter,
      child: Container(
        width: double.infinity,
        //color: Colors.white,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: _getFilesRows(),
        ),
      ),
    );
  }

  choiceFiles() async {
    var types = [
      "jpg",
      "png",
      "jpeg",
      "bmp",
      "doc",
      "docx",
      "xls",
      "xlsx",
      "pdf",
      "txt"
    ];
    FilePickerResult? result = await FilePicker.platform.pickFiles(
        allowMultiple: true, type: FileType.custom, allowedExtensions: types);
    // 选择的文件列表 从PlatformFile转换为FilePickerData
    List<String> list = [];
    bool isErrorType = false;
    if (result != null) {
      for (var element in result.files) {
        if (types.contains(element.extension)) {
          // FilePickerData d = FilePickerData(name: element.name, path: element.path!);
          list.add(element.path!);
        } else {
          isErrorType = true;
        }
      }
      var res = await _uploadFiles(list);
      setState(() {
        widget.controller.data.addAll(res);
      });
      if (isErrorType) {
        // 如果选进来的文件有不支持的格式
        LoadingUtils.showError(
            "仅支持jpg、png、jpeg、bmp、doc、docx、xls、xlsx、pdf、txt文件");
      }
      widget.onAdd?.call(res);
    } else {
      // User canceled the picker
    }
  }

  Future<List<ImagePickerData>> _uploadFiles(List<String> dataList) async {
    List<BaseUploadRequestOption> files = [];
    for (var value in dataList) {
      files.add(FileUploadRequestOption(
          type: UploadFileType.doc, filePath: value, keepFileName: true));
    }

    int failedCount = 0;
    int successCount = 0;
    List<ImagePickerData> successImages = [];
    LoadingUtils.loading(
      status: "正在上传...",
    );

    await DioClient().uploadFiles(files, hideLoading: true,
        progressListener: (response, i, t) {
      if (response?.isok != true) {
        failedCount++;
      } else {
        successCount++;
        successImages.add(ImagePickerData(
          (response!.data as UploadResult).fileName ?? "",
          (response.data as UploadResult).filePath ?? "",
          name: (response!.data as UploadResult).fileName ?? "",
          id: (response!.data as UploadResult).id ?? 0,
        ));
      }
    });
    LoadingUtils.dismiss();
    if (failedCount != 0) {
      LoadingUtils.AlertDialog("上传成功$successCount张，失败$failedCount张");
    }

    return successImages;
  }

  _getHeaderView() {
    return Container(
      padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
      width: double.infinity,
      height: 48,
      child: Row(
        children: [
          Text(
            "上传文件",
            style: TextStyle(color: "#656567".toColor()),
          ),
          Expanded(child: Container()),
          TextButton(
            onPressed: () {
              choiceFiles();
            },
            child: Row(
              children: [
                Text(
                  "点击上传",
                  style: TextStyle(color: HDColors.btnBgColor),
                ),
                Image.asset(
                  "assets/images/click_to_upload.webp",
                  height: 16,
                  width: 16,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  _getFilesRows() {
    // 过滤数据 把标记为已删除的数据删掉
    var filterData =
        widget.controller.data.where((element) => !element.isDel).toList();
    List<Widget> widgets = [];
    if (!(widget.hidehead ?? true)) {
      widgets.add(_getHeaderView());
    }

    /// 优先找出图片
    List<ImagePickerData> previewData = [];
    for (var item in filterData) {
      var fileName = item.fileName;
      if (fileName.toLowerCase().endsWith(".jpg") ||
          fileName.toLowerCase().endsWith(".png") ||
          fileName.toLowerCase().endsWith(".jpeg") ||
          fileName.toLowerCase().endsWith(".bmp")) {
        if (!(item.filePath).startsWith("http:")) {
          item.filePath = DioClient().getPreviewUrlSync(item.fileName);
        }
        previewData
            .add(ImagePickerData(item.fileName, item.filePath, name: item.name));
      }
    }

    for (var item in filterData) {
      dynamic child;
      var fileName = item.fileName;
      if (fileName.toLowerCase().endsWith(".jpg") ||
          fileName.toLowerCase().endsWith(".png") ||
          fileName.toLowerCase().endsWith(".jpeg") ||
          fileName.toLowerCase().endsWith(".bmp")) {
        child = _buildImageItem(previewData, item);
      } else {
        child = _buildFileItem(item);
      }

      if (child != null) {
        widgets.add(child);
      }
    }
    return widgets;
  }

  _buildImageItem(var previewData, var item) {
    return Container(
      width: double.infinity,
      height: 48,
      decoration: BoxDecoration(
        border: Border(
          top: BorderSide(width: 1.0, color: Theme.of(context).dividerColor), //
        ),
      ),
      child: Row(
        children: [
          InkWell(
            onTap: () {
              HDNavigator.open(ImagePreviewPage(data: previewData));
            },
            child: ImageWidget(url: item.filePath ?? "", height: 48, width: 48),
          ),
          const SizedBox(
            width: 8,
          ),
          Expanded(child: Text(item.fileName)),
          (widget.readonly ?? false)
              ? Container()
              : TextButton(
                  onPressed: () {
                    // 点击删除按钮
                    setState(() {
                      item.isDel = true;
                    });
                    widget.onRemove?.call(item);
                  },
                  style: const ButtonStyle(alignment: Alignment.centerRight),
                  child: const Text(
                    "删除",
                    style: TextStyle(color: HDColors.red),
                  ),
                )
        ],
      ),
    );
  }

  _buildFileItem(var item) {
    return Container(
      width: double.infinity,
      height: 48,
      decoration: BoxDecoration(
        border: Border(
          top: BorderSide(width: 1.0, color: Theme.of(context).dividerColor), //
        ),
      ),
      child: Row(
        children: [
          Image.asset(
            _getFileTypeIcon(item),
            width: 16,
            height: 16,
          ),
          const SizedBox(
            width: 8,
          ),
          Expanded(child: Text(item.fileName)),
          (widget.readonly ?? false)
              ? Container()
              : TextButton(
                  onPressed: () {
                    // 点击删除按钮
                    setState(() {
                      item.isDel = true;
                    });
                    widget.onRemove?.call(item);
                  },
                  style: const ButtonStyle(alignment: Alignment.centerRight),
                  child: const Text(
                    "删除",
                    style: TextStyle(color: HDColors.red),
                  ),
                )
        ],
      ),
    );
  }

  /// 设置前面的图标
  String _getFileTypeIcon(ImagePickerData data) {
    String icon = "assets/images/file_picker_txt.webp";
    switch (data.extension) {
      case "doc":
      case "docx":
        icon = "assets/images/file_picker_word.webp";
        break;
      case "xls":
      case "xlsx":
        icon = "assets/images/file_picker_excel.webp";
        break;
      case "pdf":
        icon = "assets/images/file_picker_pdf.webp";
        break;
      case "txt":
        icon = "assets/images/file_picker_txt.webp";
        break;
    }
    return icon;
  }
}

typedef CallClick<T> = void Function(T obj);

/// 文件选择控制器
class FilePickerController {
  List<ImagePickerData> data = [];
  Function? mcallback;

  /// 获取选中的文件
  List<ImagePickerData> getFiles() {
    // 不是传进来的 并且已经被删掉了 就不返回了
    return data
        .where((element) => !(!element.isInit && element.isDel))
        .toList();
  }

  _FilePickerWidgetState? _state;

  ///表示点击选择打开文件---
  void openChoseFiles() {
    mcallback?.call();
  }

  /// 添加文件
  /// 外部添加的文件选择器会自动打标记为isInit = true
  void addFiles(List<ImagePickerData> data) {
    // 传入的数据 标记为init的
    for (var element in data) {
      element.isInit = true;
    }
    this.data.addAll(data);
    // 判断控件如果已经准备就绪 就刷新控件
    if (_state?.mounted == true) {
      _state?.setState(() {});
    }
  }

  /// 清空重置数据源
  void resetFiles(List<ImagePickerData> data) {
    this.data.clear();
    addFiles(data);
  }
}

class FilePickerData {
  // todo
  String name = ""; //这个表示objectname
  String fileName = ""; //这个表示文件名字
  String path = "";
  bool isInit = false;
  bool isDel = false;
  String extension = "";
  int id = 0;

  FilePickerData(
      {required this.name,
      required this.path,
      required this.fileName,
      required this.id});

  FilePickerData.fromJson(Map<String, dynamic> json) {
    name = json['name'] ?? "";
    fileName = json['fileName'] ?? "";
    path = json['path'] ?? "";
    isInit = json['isInit'] ?? false;
    isDel = json['isDel'] ?? false;
    id = json['id'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = Map<String, dynamic>();
    data['name'] = name;
    data['fileName'] = fileName;
    data['path'] = path;
    data['isInit'] = isInit;
    data['isDel'] = isDel;
    data['id'] = id;
    return data;
  }
}
